package com.ruoyi.store.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.core.page.PagePlus;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.store.service.IHmSystemAttachmentService;
import com.ruoyi.store.vo.CategoryTreeVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.store.bo.HmCategoryAddBo;
import com.ruoyi.store.bo.HmCategoryQueryBo;
import com.ruoyi.store.bo.HmCategoryEditBo;
import com.ruoyi.store.domain.HmCategory;
import com.ruoyi.store.mapper.HmCategoryMapper;
import com.ruoyi.store.vo.HmCategoryVo;
import com.ruoyi.store.service.IHmCategoryService;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 商品分类Service业务层处理
 *
 * @author ruoyi
 * @date 2021-07-02
 */
@Service
public class HmCategoryServiceImpl extends ServicePlusImpl<HmCategoryMapper, HmCategory> implements IHmCategoryService {

	@Resource
	private HmCategoryMapper dao;

	@Autowired
	private IHmSystemAttachmentService systemAttachmentService;

    @Override
    public HmCategoryVo queryById(Integer id){
        return getVoById(id, HmCategoryVo.class);
    }

    @Override
    public TableDataInfo<HmCategoryVo> queryPageList(HmCategoryQueryBo bo) {
        PagePlus<HmCategory, HmCategoryVo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo), HmCategoryVo.class);
        return PageUtils.buildDataInfo(result);
    }

    @Override
    public List<HmCategoryVo> queryList(HmCategoryQueryBo bo) {
        return listVo(buildQueryWrapper(bo), HmCategoryVo.class);
    }

    private LambdaQueryWrapper<HmCategory> buildQueryWrapper(HmCategoryQueryBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<HmCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getPid() != null, HmCategory::getPid, bo.getPid());
        lqw.eq(StrUtil.isNotBlank(bo.getPath()), HmCategory::getPath, bo.getPath());
        lqw.like(StrUtil.isNotBlank(bo.getName()), HmCategory::getName, bo.getName());
        lqw.eq(bo.getType() != null, HmCategory::getType, bo.getType());
        lqw.eq(StrUtil.isNotBlank(bo.getUrl()), HmCategory::getUrl, bo.getUrl());
        lqw.eq(StrUtil.isNotBlank(bo.getExtra()), HmCategory::getExtra, bo.getExtra());
        lqw.eq(bo.getStatus() != null, HmCategory::getStatus, bo.getStatus());
        lqw.eq(bo.getSort() != null, HmCategory::getSort, bo.getSort());
        return lqw;
    }

    @Override
    public Boolean insertByAddBo(HmCategoryAddBo bo) {
        HmCategory add = BeanUtil.toBean(bo, HmCategory.class);
        validEntityBeforeSave(add);
		add.setCreateTime(DateUtils.getNowDate());
		add.setUpdateTime(DateUtils.getNowDate());
        return save(add);
    }

    @Override
    public Boolean updateByEditBo(HmCategoryEditBo bo) {
		String value = systemAttachmentService.clearPrefix(bo.getExtra());
		bo.setExtra(value);
        HmCategory update = BeanUtil.toBean(bo, HmCategory.class);
        validEntityBeforeSave(update);
		update.setUpdateTime(DateUtils.getNowDate());
        return updateById(update);
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(HmCategory entity){
        //TODO 做一些数据校验,如唯一约束
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Integer> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return removeByIds(ids);
    }

	/**
	 * 带结构的无线级分类
	 */
	@Override
	public List<CategoryTreeVo> getListTree(Integer type, Integer status, String name) {
		return getTree(type, status,name,null);
	}
	/**
	 * 带结构的无线级分类
	 * @author Mr.Zhang
	 * @since 2020-04-16
	 */
	private List<CategoryTreeVo> getTree(Integer type, Integer status,String name, List<Integer> categoryIdList) {
		//循环数据，把数据对象变成带list结构的vo
		List<CategoryTreeVo> treeList = new ArrayList<>();

		LambdaQueryWrapper<HmCategory> lambdaQueryWrapper = Wrappers.lambdaQuery();
		lambdaQueryWrapper.eq(HmCategory::getType, type);

		if(null != categoryIdList && categoryIdList.size() > 0){
			lambdaQueryWrapper.in(HmCategory::getId, categoryIdList);
		}

		if(status >= 0){
			lambdaQueryWrapper.eq(HmCategory::getStatus, status==1?true:false);
		}
		if(StringUtils.isNotBlank(name)){ // 根据名称模糊搜索
			lambdaQueryWrapper.like(HmCategory::getName,name);
		}

		lambdaQueryWrapper.orderByDesc(HmCategory::getSort);
		lambdaQueryWrapper.orderByAsc(HmCategory::getId);
		List<HmCategory> allTree = dao.selectList(lambdaQueryWrapper);
		if(allTree == null){
			return null;
		}
		// 根据名称搜索特殊处理 这里仅仅处理两层搜索后有子父级关系的数据
		if(StringUtils.isNotBlank(name) && allTree.size() >0){
			List<HmCategory> searchCategory = new ArrayList<>();
			List<Integer> categoryIds = allTree.stream().map(HmCategory::getId).collect(Collectors.toList());

			List<Integer> pidList = allTree.stream().filter(c -> c.getPid() > 0 && !categoryIds.contains(c.getPid()))
				.map(HmCategory::getPid).distinct().collect(Collectors.toList());
			if (CollUtil.isNotEmpty(pidList)) {
				pidList.forEach(pid -> {
					searchCategory.add(dao.selectById(pid));
				});
			}
			allTree.addAll(searchCategory);
		}

		for (HmCategory category: allTree) {
			CategoryTreeVo categoryTreeVo = new CategoryTreeVo();
			BeanUtils.copyProperties(category, categoryTreeVo);
			treeList.add(categoryTreeVo);
		}


		//返回
		Map<Integer, CategoryTreeVo> map = new HashMap<>();
		//ID 为 key 存储到map 中
		for (CategoryTreeVo categoryTreeVo1 : treeList) {
			map.put(categoryTreeVo1.getId(), categoryTreeVo1);
		}

		List<CategoryTreeVo> list = new ArrayList<>();
		for (CategoryTreeVo tree : treeList) {
			//子集ID返回对象，有则添加。
			CategoryTreeVo tree1 = map.get(tree.getPid());
			if(tree1 != null){
				tree1.getChild().add(tree);
			}else {
				list.add(tree);
			}
		}
		System.out.println("无限极分类 : getTree:" + JSON.toJSONString(list));
		return list;
	}
}
